#!/usr/bin/env python
# encoding: utf-8
from loguru import logger
from lycium.kafka.protocol.kafkapacket_pb2 import KafkaPacket
from lycium.kafka.kafkaWorker import KafkaWorker

from methods.hello import hello_world

from config import load_config
import const
from context import Context

import json
import asyncio

config_param = load_config()

kafak_worker = KafkaWorker(config_param["kafka"]["conn"]["hosts"],
                            private_topic=config_param["kafka"]["private_topic"],
                            group_id=config_param["kafka"]["group"],
                            sasl_username=config_param["kafka"]["conn"]["username"],
                            sasl_password=config_param["kafka"]["conn"]["password"]
                            )

class Router(object):
    """ 
    路由类，辅助解决一下重现性工作
    """
    def __init__(self):
        self._method_mapping = {}
        self._engine = None
        self.init_route()

    async def init_environment(self):
        pass

    def init_route(self):
        """初始化路由信息 """
        self.add_read(hello_world,"Hello")
        

    def _add_method(self,callback: callable,module_name:str,permission:str,method_name:str=""):
        """ 
        添加一个方法
        """
        if method_name == "":
            method_name = callback.__name__
        if method_name not in self._method_mapping:
            self._method_mapping[method_name] ={"callback":callback,"module_name":module_name,"permission":permission}
        else:
            logger.error("重复添加 {0}".format(method_name))
    
    def add_read(self,callback: callable,module_name:str,method_name:str=""):
        self._add_method(callback,module_name,"read_permission",method_name)

    def add_create(self,callback: callable,module_name:str,method_name:str=""):
        self._add_method(callback,module_name,"create_permission",method_name)

    def add_update(self,callback: callable,module_name:str,method_name:str=""):
        self._add_method(callback,module_name,"create_permission",method_name)

    def add_delete(self,callback: callable,module_name:str,method_name:str=""):
        self._add_method(callback,module_name,"update_permission",method_name)

    async def service(self,message:KafkaPacket):
        """ 
        提供服务的入口
        """
        try:
            c = Context(message,self,kafak_worker)
            c.add_middleware(self.route)
            return await c.next()

        except Exception as e:
            logger.exception(e)
            return {
                "code":const.ERR_SERVICE,
                "msg":str(e)
            }

    async def route(self,context:Context):
        """ 
        路由功能
        """
        payload = json.loads(context.request.body)
        callback = self._method_mapping[payload["method"]]["callback"]

        if asyncio.iscoroutinefunction(callback) or asyncio.iscoroutine(callback):
            return await callback(payload,self._engine,context)
        return callback(payload,self._engine,context)

router = Router()
